/***************************************************************************
 *   This is a part of the NextCAD Web APP.                                *
 *   Copyright (C) AMCAX, All rights reserved.                             *
 ***************************************************************************/

// import { Alert, Button } from 'antd';
import {
  pickedFaceData,
  pickedLineData,
  pickedVertexData,
  pickedModelData,
} from '@amcax/base';
import { PickInputRJSFFormat } from '@app-cad/common/components/command-form/constants';
import { PickableCommandForm } from '@app-cad/common/components/command-form/pickable';
import { useCommand } from '@app-cad/common/hooks/useCommand';
import { useTools } from '@app-cad/common/hooks/useTools';
import { CurvedBaseCommand, CurvedCmdDialogParams } from '@app-cad/types';
import { RJSFSchema } from '@rjsf/utils';
import { useAsyncEffect } from 'ahooks';
import i18n from 'i18next';
import { useEffect, useState, useRef } from 'react';
import './index.scss';
import { getIdOfPickedObj } from '@app-base/common/utils/render';

// 老的参数信息，保持方便兼容老数据
type CurveType = {
  id: string;
  reverse: boolean; // 是否反向
  surface?: string; // 支持面
  continuity?: number; // 支持面的连续性： 0(连接)， 1(相切)
  conPoint?: string; // 封闭曲线的闭合点
};

type RailType = {
  id: string;
  surface?: string; // 支持面
  continuity?: number;
};

type OldParams = {
  curves: CurveType[];
  rails: string[];
};

type Params = {
  curves: CurveType[];
  rails: RailType[];
};

type CurvePickedType = pickedLineData | pickedModelData; // 曲线、草图

type FormDataType = {
  curves: {
    curve: CurvePickedType;
    reverse: boolean;
    surface?: pickedFaceData;
    continuity?: number;
    conPoint?: pickedVertexData;
  }[];
  rails: {
    rail: pickedLineData;
    surface?: pickedFaceData;
    continuity?: number;
  }[];
};

// 多截面曲面
function CmdLoftSurface({ title, onClose, props }: CurvedCmdDialogParams) {
  const initData = {
    curves: [
      { curve: null, reverse: false },
      { curve: null, reverse: false },
    ],
    rails: [],
  };

  const [formData, setFormData] = useState<FormDataType>(initData);
  const lastPreviewData = useRef<string>(null);

  const { picker } = useTools();

  useAsyncEffect(async () => {
    if (props == null) {
      setFormData(initData);
      return;
    }

    // 兼容老数据
    let isOldParams = false;
    if (
      props.params?.rails != null &&
      props.params.rails.length > 0 &&
      typeof props.params.rails[0] === 'string'
    ) {
      isOldParams = true;
    }

    if (isOldParams) {
      const params: OldParams = props.params;
      const { curves, rails } = params;

      await initEditDependency([...curves.map((c) => c.id), ...rails]);

      setFormData({
        curves: curves.map((curve) => {
          const line = picker.generatePickObjByPickID(curve.id, {
            showArrow: true,
          }) as pickedLineData;
          if (curve.reverse) {
            line.assisObj.reverse();
          }

          return {
            curve: line,
            reverse: curve.reverse,
          };
        }),
        rails: rails.map((id) => {
          return {
            rail: picker.generatePickObjByPickID(id) as pickedLineData,
            surface: undefined,
            continuity: undefined,
          };
        }),
      });
    } else {
      const params: Params = props.params;
      const { curves, rails } = params;

      await initEditDependency([
        ...curves.map((c) => c.id),
        ...curves.map((c) => c.surface),
        ...curves.map((c) => c.conPoint),
        ...rails.map((r) => r.id),
        ...rails.map((r) => r.surface),
      ]);

      setFormData({
        curves: curves.map((curve) => {
          const line = picker.generatePickObjByPickID(curve.id, {
            showArrow: true,
          });
          if ((line as pickedLineData)?.edgeId && curve.reverse) {
            (line as pickedLineData).assisObj.reverse();
          }

          return {
            curve: line as CurvePickedType,
            reverse: curve.reverse,
            surface: curve.surface
              ? (picker.generatePickObjByPickID(
                  curve.surface,
                ) as pickedFaceData)
              : null,
            continuity: curve.continuity,
            conPoint: curve.conPoint
              ? (picker.generatePickObjByPickID(
                  curve.conPoint,
                ) as pickedVertexData)
              : null,
          };
        }),
        rails: rails.map((rail) => {
          return {
            rail: picker.generatePickObjByPickID(rail.id) as pickedLineData,
            surface: rail.surface
              ? (picker.generatePickObjByPickID(rail.surface) as pickedFaceData)
              : null,
            continuity: rail.continuity,
          };
        }),
      });
    }
  }, [props?.shape]);

  const isFormDataValid = () => {
    const { curves } = formData;

    return curves.filter((c) => c && c.curve != null).length >= 2;
  };

  useEffect(() => {
    if (!isFormDataValid()) {
      clear();
      lastPreviewData.current = null;
      return;
    }

    const curParamStr = JSON.stringify(generateCmdParams());
    if (curParamStr === lastPreviewData.current) {
      // console.log('预览数据未变化，跳过预览更新');
      return;
    }
    // console.log(curParamStr);
    lastPreviewData.current = curParamStr;
    // clear(); // no clear preview, let user can see the last preview

    preview();
  }, [formData]);

  const checkAndFinishDraw = async () => {
    if (!isFormDataValid()) {
      return;
    }

    await execute(false);
    onClose();
  };

  const { initEditDependency, initingEdit, clear, confirmCommand, isLoading } =
    useCommand('cmd-loft-surface', {
      commandName: 'CreateSurface',
      editDxid: props?.shape,
      onClose,
      finishDraw: checkAndFinishDraw,
    });

  const preview = async () => {
    await execute(true);
  };

  const generateCmdParams = () => {
    const { curves, rails } = formData;
    return {
      curves: curves
        .filter((c) => c && c.curve != null)
        .map((item) => {
          return {
            id: getIdOfPickedObj(item.curve),
            reverse: (item.curve as pickedLineData)?.assisObj?.isReversed,
            surface: item.surface?.meshId,
            continuity: item.continuity,
            conPoint: item.conPoint?.vertexId,
          };
        }),
      rails: rails
        .filter((c) => c && c.rail != null)
        .map((item) => {
          return {
            id: item.rail.edgeId,
            surface: item.surface?.meshId,
            continuity: item.continuity,
          };
        }),
    };
  };

  const execute = async (preview: boolean) => {
    const params = {
      type: 'Loft',
      a: generateCmdParams(),
    };

    await confirmCommand(params, preview);
  };

  const schema: RJSFSchema = {
    type: 'object',
    properties: {
      curves: {
        type: 'array',
        title: '截面曲线',
        items: {
          type: 'object',
          title: '通过点',
          properties: {
            curve: {
              type: 'string',
              title: '截面',
              format: PickInputRJSFFormat.PickSketchCurve,
            },
            surface: {
              type: 'string',
              title: '支持面',
              format: PickInputRJSFFormat.PickSurface,
            },
            continuity: {
              type: 'number',
              title: '连续性',
              oneOf: [
                {
                  type: 'number',
                  title: '连接',
                  const: 0,
                },
                {
                  type: 'number',
                  title: '相切',
                  const: 1,
                },
                // {
                //   type: 'number',
                //   title: '曲率',
                //   const: 2,
                // },
              ],
              default: 1,
            },
            conPoint: {
              type: 'string',
              title: '闭合点',
              format: PickInputRJSFFormat.PickVertex,
            },
          },
        },
        uniqueItems: true,
      },
      rails: {
        type: 'array',
        title: '引导线',
        items: {
          type: 'object',
          title: '通过点',
          properties: {
            rail: {
              type: 'string',
              title: '引导线',
              format: PickInputRJSFFormat.PickCurve,
            },
            surface: {
              type: 'string',
              title: '支持面',
              format: PickInputRJSFFormat.PickSurface,
            },
            continuity: {
              type: 'number',
              title: '连续性',
              oneOf: [
                {
                  type: 'number',
                  title: '连接',
                  const: 0,
                },
                {
                  type: 'number',
                  title: '相切',
                  const: 1,
                },
                // {
                //   type: 'number',
                //   title: '曲率',
                //   const: 2,
                // },
              ],
              default: 1,
            },
          },
        },
        uniqueItems: true,
      },
    },
  };

  return (
    <PickableCommandForm
      disabled={initingEdit}
      onClose={onClose}
      title={title}
      schema={schema}
      submitLoading={isLoading}
      onChange={(v) => {
        // 处理表单数据变化，如果最后一个截面曲线或引导线不为空，则添加新的空项
        const newCurves = [...v.curves];
        if (newCurves[newCurves.length - 1]?.curve != null) {
          newCurves.push({ curve: null, reverse: false });
        }
        const newRails = [...v.rails];
        if (newRails[newRails.length - 1]?.rail != null) {
          newRails.push({});
        }

        setFormData({ curves: newCurves, rails: newRails });
      }}
      formData={formData}
      submitText='完成'
      onSubmit={checkAndFinishDraw}
      extraUiSchema={{
        'ui:options': {
          classNames:
            'command-form command-form-array command-form_cmd-cad-loft-surface',
        },
        curves: {
          items: {
            curve: {
              'ui:placeholder': '请输入截面曲线',
              'ui:autofocus': true,
              'ui:options': {
                showArrow: true,
                curveReversable: true,
              },
            },
            surface: {
              'ui:placeholder': '请输入支持面',
              'ui:options': {
                canBeAutoFocused: false,
                allowInfinitePlane: true,
              },
            },
            conPoint: {
              'ui:placeholder': '请输入闭合点',
              'ui:options': {
                canBeAutoFocused: false,
              },
            },
          },
        },
        rails: {
          items: {
            rail: {
              'ui:placeholder': '请输入引导线',
              'ui:autofocus': true,
            },
            surface: {
              'ui:placeholder': '请输入支持面',
              'ui:options': {
                canBeAutoFocused: false,
                allowInfinitePlane: true,
              },
            },
          },
        },
      }}
      isFormDataValid={isFormDataValid()}
    />
  );
}

export const cmdLoftSurface: CurvedBaseCommand = {
  id: 'CmdLoftSurfance',
  label: 'command.loft-surface',
  icon: 'commands/curved/multi-sections-surface',
  help: {
    remark: 'tips.redo',
  },
  create: (label, onClose, props) => (
    <CmdLoftSurface
      title={i18n.t(label)}
      onClose={onClose}
      props={props}
    />
  ),
};
